package com.dm.cloud.utils.mingexcel.worker;

import com.dm.cloud.utils.mingexcel.annotions.ColumnProperties;
import com.dm.cloud.utils.mingexcel.annotions.DropdownProperties;
import com.dm.cloud.utils.mingexcel.annotions.ExcelProperties;
import com.dm.cloud.utils.mingexcel.entity.TransferItem;
import com.dm.cloud.utils.mingexcel.enums.SameCellMergeEnum;
import com.dm.cloud.utils.mingexcel.medium.Merger;
import com.dm.cloud.utils.mingexcel.medium.PropertiesInitializer;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public abstract class SheetWriterFrame {

    /////////////////////////通用全局属性
    //表格名称
    String sheetName = "";
    //属性初始化
    public PropertiesInitializer propertiesInitializer = new PropertiesInitializer();
    //标题
    TitileBuilder titileBuilder;
    //合并表头
    MergedHeadersBuilder mergedHeadersBuilder;
    //行生成器
    RowBuilder rowBuilder;
    //字段转换器
    TransferWorker transferWorker = new TransferWorker();
    //类型
    Class<?> clazz;
    //需要导出的数据
    List<?> data ;
    //导出的所有列数
    public int allColumns = 0 ;
    //导出已经写入的行数
    public int writedRows = 0 ;
    //导出已经写入的行数
    public int contentStartRow = 0 ;

    public SheetWriterFrame(Class<?> clazz, List<?> data) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        this.clazz = clazz;
        this.data = data;
        //先解析类上的注解
        ExcelProperties excelProperties = clazz.getAnnotation(ExcelProperties.class);
        if(null != excelProperties){
            //表格名字
            this.sheetName = excelProperties.sheetName();
            //excel标题
            if(null != excelProperties.title()){
                this.titileBuilder = new TitileBuilder(excelProperties.title());
            }
            if(null != excelProperties.mergedHeaders()){
                this.mergedHeadersBuilder = new MergedHeadersBuilder(excelProperties.mergedHeaders());
            }
            this.rowBuilder = new RowBuilder(excelProperties.row());
        }

        //循环字段设置单元格属性
        Field[] tFields = clazz.getDeclaredFields();
        for (int i = 0; i < tFields.length; i++) {
            Field f = tFields[i];
            f.setAccessible(true);
            //列属性 有此属性的字段才导出
            ColumnProperties columnProperties = f.getAnnotation(ColumnProperties.class);
            //下拉框属性
            DropdownProperties dropdownProperties = f.getAnnotation(DropdownProperties.class);
            if(null!=columnProperties){
                allColumns++;
                if(null !=dropdownProperties){
                    Integer index = columnProperties.index();
                    Class dpclz = dropdownProperties.clazz();
                    //调用方法 返回下拉框列表
                    Object obj = dpclz.newInstance();
                    //获取方法
                    Method method = MethodUtils.getMatchingAccessibleMethod(dpclz, transferWorker.methodName);
                    method.setAccessible(true);
                    //调用方法
                    Object result = method.invoke(obj);

                    if(result!=null && result instanceof TransferItem[]){
                        transferWorker.addFormater(index,(TransferItem[])result);
                    }
                }
            }
        }
    }

    /**
     * 写表格内容
     * @param wb
     * @throws IllegalAccessException
     */
    public void writeSheet(XSSFWorkbook wb) throws IllegalAccessException {
        XSSFSheet sheet = this.createSheet(wb);
        this.contentStartRow = this.writedRows;
        this.createDataContent(wb, sheet);

        //合并相同行
        ExcelProperties excelProperties = clazz.getAnnotation(ExcelProperties.class);
        Merger.mergeSameCells(sheet,excelProperties.sameMerge(),this.contentStartRow,this.allColumns);

        //自适应宽度最后执行
        Field[] tFields = clazz.getDeclaredFields();
        for (int i = 0; i < tFields.length; i++) {
            Field f = tFields[i];
            f.setAccessible(true);
            ColumnProperties columnProperties = f.getAnnotation(ColumnProperties.class);
            if(null != columnProperties){
                if(columnProperties.autoWidth()){
                    sheet.autoSizeColumn(columnProperties.index());
                }
            }
        }
    };


    /**
     * 初始化表格
     * 标题、表头、合并表头等
     * @param wb
     * @return
     * @throws IllegalAccessException
     */
    abstract XSSFSheet createSheet(XSSFWorkbook wb) throws IllegalAccessException;

    /**
     * 创建导出内容
     * @param wb
     * @param sheet
     * @throws IllegalAccessException
     */
    abstract void createDataContent(XSSFWorkbook wb, XSSFSheet sheet) throws IllegalAccessException;

    /**
     * firstRow 开始行号(下标0开始)
     * lastRow  结束行号，最大65535
     * firstCol 区域中第一个单元格的列号 (下标0开始)
     * lastCol 区域中最后一个单元格的列号
     * dataArray 下拉内容
     * sheetHidden 隐藏的sheet编号（例如1,2,3），多个下拉数据不能使用同一个
     * */
    void selectList(XSSFSheet sheet,int firstRow, int lastRow, int firstCol, int lastCol, String[] dataArray){
        XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
        XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper.createExplicitListConstraint(dataArray);
        CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
        XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, addressList);
        validation.setSuppressDropDownArrow(true);
        validation.setShowErrorBox(true);
        sheet.addValidationData(validation);
    }
}
